home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / daemons / nfs / nfs-serv.2be / nfs-serv / nfs-server-2.2beta16 / nfs_dispatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-31  |  7.6 KB  |  306 lines

  1. /*
  2.  * dispatch.c    This file contains the function dispatch table.
  3.  *
  4.  * Authors:    Donald J. Becker, <becker@super.org>
  5.  *        Rick Sladkey, <jrs@world.std.com>
  6.  *        Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  7.  *        Olaf Kirch, <okir@monad.swb.de>
  8.  *
  9.  *        This software may be used for any purpose provided
  10.  *        the above copyright notice is retained.  It is supplied
  11.  *        as is, with no warranty expressed or implied.
  12.  */
  13.  
  14. #include "nfsd.h"
  15. #include "nfs_prot.h"
  16. #include "rpcmisc.h"
  17.  
  18. /*
  19.  * These are the global variables that hold all argument and result data.
  20.  */
  21. union argument_types     argument;
  22. union result_types    result;
  23.  
  24. /*
  25.  * This is a dispatch table to simplify error checking,
  26.  * and supply return attributes for NFS functions.
  27.  */
  28.  
  29. #ifdef __STDC__
  30. #define CONCAT(a,b)    a##b
  31. #define CONCAT3(a,b,c)    a##b##c
  32. #define STRING(a)    #a
  33. #else
  34. #define CONCAT(a,b)    a/**/b
  35. #define CONCAT3(a,b,c)    a/**/b/**/c
  36. #define STRING(a)    "a"
  37. #endif
  38.  
  39. #define table_ent(res_type, arg_type, funct) {            \
  40.     sizeof(res_type), sizeof(arg_type),            \
  41.     (xdrproc_t) CONCAT(xdr_,res_type),            \
  42.     (xdrproc_t) CONCAT(xdr_,arg_type),            \
  43.     (int (*)()) CONCAT3(nfsd_nfsproc_,funct,_2),        \
  44.     STRING(funct), CONCAT(pr_,arg_type)            \
  45. }
  46.  
  47. /* This definition makes the first table entry use xdr_char instead of
  48.  * xdr_void. The NULL procedure call over TCP fails for this reason
  49. #define nil    char
  50.  */
  51. #define nil    void
  52. #define xdr_nil    xdr_void
  53. #define pr_nil    pr_void
  54. #define pr_char    pr_void
  55.  
  56. struct dispatch_entry {
  57.     int        res_size, arg_size;    /* sizeof the res/arg structs    */
  58.     xdrproc_t    xdr_result;
  59.     xdrproc_t    xdr_argument;
  60.     int        (*funct)();        /* function handler        */
  61.     char    *name;            /* name of function        */
  62.     char    *(*log_print)();    /* ptr to debug handler        */
  63. };
  64.  
  65. static _PRO( char *pr_void, (void)                    );
  66. static _PRO( char *pr_nfs_fh, (nfs_fh *argp)                );
  67. static _PRO( char *pr_sattrargs, (sattrargs *argp)            );
  68. static _PRO( char *pr_diropargs, (diropargs *argp)            );
  69. static _PRO( char *pr_readargs, (readargs *argp)            );
  70. static _PRO( char *pr_writeargs, (writeargs *argp)            );
  71. static _PRO( char *pr_createargs, (createargs *argp)            );
  72. static _PRO( char *pr_renameargs, (renameargs *argp)            );
  73. static _PRO( char *pr_linkargs, (linkargs *argp)            );
  74. static _PRO( char *pr_symlinkargs, (symlinkargs *argp)            );
  75. static _PRO( char *pr_readdirargs, (readdirargs *argp)            );
  76.  
  77. static struct dispatch_entry dtable[] = {
  78.     table_ent(nil,nil,null),            /* NULL */
  79.     table_ent(attrstat,nfs_fh,getattr),        /* GETATTR */
  80.     table_ent(attrstat,sattrargs,setattr),        /* SETATTR */
  81.     table_ent(nil,nil,root),            /* ROOT */
  82.     table_ent(diropres,diropargs,lookup),        /* LOOKUP */
  83.     table_ent(readlinkres,nfs_fh,readlink),        /* READLINK */
  84.     table_ent(readres,readargs,read),        /* READ */
  85.     table_ent(nil,nil,writecache),            /* WRITECACHE */
  86.     table_ent(attrstat,writeargs,write),        /* WRITE */
  87.     table_ent(diropres,createargs,create),        /* CREATE */
  88.     table_ent(nfsstat,diropargs,remove),        /* REMOVE */
  89.     table_ent(nfsstat,renameargs,rename),        /* RENAME */
  90.     table_ent(nfsstat,linkargs,link),        /* LINK */
  91.     table_ent(nfsstat,symlinkargs,symlink),        /* SYMLINK */
  92.     table_ent(diropres,createargs,mkdir),        /* MKDIR */
  93.     table_ent(nfsstat,diropargs,rmdir),        /* RMDIR */
  94.     table_ent(readdirres,readdirargs,readdir),    /* READDIR */
  95.     table_ent(statfsres,nfs_fh,statfs),        /* STATFS */
  96. };
  97.  
  98. #ifdef CALL_PROFILING
  99. #define PATH_PROFILE    "/tmp/nfsd.profile"
  100.  
  101. static struct timeval    rtimes[18] = {
  102.     {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
  103.     {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
  104.     {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}
  105. };
  106. static int        calls[18] = {
  107.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  108. };
  109. static struct timeval    t0, t1;
  110. #endif
  111.  
  112.  
  113. /*
  114.  * The main dispatch routine.
  115.  */
  116. void nfs_dispatch(rqstp, transp)
  117. struct svc_req *rqstp;
  118. SVCXPRT *transp;
  119. {
  120.     unsigned int proc_index = rqstp->rq_proc;
  121.     struct dispatch_entry *dent;
  122.  
  123.     _rpcsvcdirty = 1;
  124.  
  125.     if (proc_index >= (sizeof(dtable) / sizeof(dtable[0]))) {
  126.         svcerr_noproc(transp);
  127.         goto done;
  128.     }
  129.     dent = &dtable[proc_index];
  130.  
  131. #ifdef CALL_PROFILING
  132.     gettimeofday(&t0, NULL);
  133. #endif
  134.  
  135.     /* Initialize our variables for determining the attributes of
  136.      * the file system in nfsd.c */
  137.     nfsclient = NULL;
  138.  
  139.     memset(&argument, 0, dent->arg_size);
  140.     if (!svc_getargs(transp, dent->xdr_argument, &argument)) {
  141.         svcerr_decode(transp);
  142.         goto done;
  143.     }
  144.     /* Clear the result structure. */
  145.     memset(&result, 0, dent->res_size);
  146.  
  147.     /* Log the call. The if() saves us a superfluous call to the debug
  148.      * functions, which is a big performance win.
  149.      */
  150.     if (logging_enabled(D_CALL))
  151.         log_call(rqstp, dent->name, dent->log_print(&argument));
  152.  
  153.     /* Do the function call itself. */
  154.     result.nfsstat = (*dent->funct) (&argument, rqstp);
  155.     dprintf(D_CALL, "result: %d\n", result.nfsstat);
  156.  
  157.     if (/* result.nfsstat >= 0 && */ /* nfsstat is unsigned? */
  158.       !svc_sendreply(transp, dent->xdr_result, (caddr_t) & result)) {
  159.         svcerr_systemerr(transp);
  160.     }
  161.     if (!svc_freeargs(transp, dent->xdr_argument, &argument)) {
  162.         dprintf(L_ERROR, "unable to free RPC arguments, exiting\n");
  163.         exit(1);
  164.     }
  165. #ifdef CALL_PROFILING
  166.     gettimeofday(&t1, NULL);
  167.  
  168.     if (t1.tv_usec < t0.tv_usec) {
  169.         rtimes[proc_index].tv_sec += t1.tv_sec - t0.tv_sec - 1;
  170.         rtimes[proc_index].tv_usec += 1000000 + t1.tv_usec - t0.tv_usec;
  171.     } else {
  172.         rtimes[proc_index].tv_sec += t1.tv_sec - t0.tv_sec;
  173.         rtimes[proc_index].tv_usec += t1.tv_usec - t0.tv_usec;
  174.     }
  175.     calls[proc_index]++;
  176. #endif
  177.  
  178. done:
  179.     _rpcsvcdirty = 0;
  180.     if (need_reinit) {
  181.         reinitialize(0);
  182.     }
  183.     if (need_flush) {
  184.         flush_cache(0);
  185.     }
  186. }
  187.  
  188. #ifdef CALL_PROFILING
  189. void
  190. dump_stats(int sig)
  191. {
  192.     FILE    *fp;
  193.     int    i;
  194.  
  195.     signal (sig, dump_stats);
  196.  
  197.     if ((fp = fopen(PATH_PROFILE, "w")) == NULL) {
  198.         dprintf(L_WARNING, "unable to write profile data to %s\n",
  199.                 PATH_PROFILE);
  200.         return;
  201.     }
  202.  
  203.     for (i = 0; i < 18; i++) {
  204.         float t;
  205.  
  206.         t = (float) rtimes[i].tv_sec +
  207.             (float) rtimes[i].tv_usec / 1000000.0;
  208.         fprintf(fp, "%-20s\t%5d calls %8.4f sec avg\n",
  209.                 dtable[i].name, calls[i],
  210.                 (calls[i])?  t / calls[i] : 0);
  211.         rtimes[i].tv_sec = rtimes[i].tv_usec = 0;
  212.         calls[i] = 0;
  213.     }
  214.  
  215.     fclose (fp);
  216. }
  217. #endif
  218.  
  219.  
  220. /*
  221.  * Functions for debugging output. This is still risky, because malformed
  222.  * requests could overwrite our data segment.
  223.  */
  224. static char    printbuf[2048];
  225.  
  226. static char *pr_void()
  227. {
  228.     return ("");
  229. }
  230.  
  231. static char *pr_nfs_fh(argp)
  232. nfs_fh *argp;
  233. {
  234.     return (fh_pr(argp));
  235. }
  236.  
  237. static char *pr_sattrargs(argp)
  238. sattrargs *argp;
  239. {
  240.     sprintf(printbuf, "fh:%s m:%0o u/g:%d/%d size:%d atime:%#x mtime:%#x",
  241.         fh_pr(&argp->file), argp->attributes.mode,
  242.         argp->attributes.uid, argp->attributes.gid,
  243.         argp->attributes.size,
  244.      argp->attributes.atime.seconds, argp->attributes.mtime.seconds);
  245.     return (printbuf);
  246. }
  247.  
  248. static char *pr_diropargs(argp)
  249. diropargs *argp;
  250. {
  251.     sprintf(printbuf, "fh:%s n:%s", fh_pr(&(argp->dir)), argp->name);
  252.     return (printbuf);
  253. }
  254.  
  255. static char *pr_readargs(argp)
  256. readargs *argp;
  257. {
  258.     sprintf(printbuf, "%s: %d bytes at %d",
  259.         fh_pr(&argp->file), argp->count, argp->offset);
  260.     return (printbuf);
  261. }
  262.  
  263. static char *pr_writeargs(argp)
  264. writeargs *argp;
  265. {
  266.     sprintf(printbuf, "%s: %d bytes at %d",
  267.         fh_pr(&argp->file), argp->data.data_len, argp->offset);
  268.     return (printbuf);
  269. }
  270.  
  271. static char *pr_createargs(argp)
  272. createargs *argp;
  273. {
  274.     sprintf(printbuf, "fh:%s n:%s m:%0o u/g:%d/%d size:%d atime:%#x mtime:%#x",
  275.         fh_pr(&argp->where.dir), argp->where.name,
  276.         argp->attributes.mode, argp->attributes.uid,
  277.         argp->attributes.gid, argp->attributes.size,
  278.      argp->attributes.atime.seconds, argp->attributes.mtime.seconds);
  279.     return (printbuf);
  280. }
  281.  
  282. static char *pr_renameargs(argp)
  283. renameargs *argp;
  284. {
  285.     return ("");
  286. }
  287.  
  288. static char *pr_linkargs(argp)
  289. linkargs *argp;
  290. {
  291.     return ("");
  292. }
  293.  
  294. static char *pr_symlinkargs(argp)
  295. symlinkargs *argp;
  296. {
  297.     return ("");
  298. }
  299.  
  300. static char *pr_readdirargs(argp)
  301. readdirargs *argp;
  302. {
  303.     return (fh_pr(&argp->dir));
  304. }
  305.  
  306.